package com.querie.controller;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import com.querie.config.Configuration;
import com.querie.sql.ConnectionFactory;

public class ModelInputController {
	
	static int numOfFolds = Configuration.getNumOfFolds(); 
	
	private static class Fold{
		int startIndex;
		int endIndex;
	}
	
	
	public static void buildModelInput() {
		
		System.out.println("Model Input Generation Starts");
		
		try {		
			
			Fold[] aFold = new Fold[numOfFolds];
			
			ResultSet rs = null;
		    PreparedStatement stmt = null;
		    Connection conn = ConnectionFactory.getConnection();
		    conn.setAutoCommit(false);
		    conn.setTransactionIsolation(conn.TRANSACTION_SERIALIZABLE);
		    
			int iSessioncount, iTrainingSessionCount, iTestSessionCount;
			
			
			stmt = conn.prepareStatement("select count(distinct (sessionid)) as totalsessions from query");
		    rs = stmt.executeQuery();
		    
		    rs.next();
			iSessioncount = rs.getInt("totalsessions");
		    System.out.println("Sessioncount: " + iSessioncount);
		    
			long[] aSessionId = new long[iSessioncount];		    
			
			stmt = conn.prepareStatement("select distinct (sessionid) as sessionid from query");
		    rs = stmt.executeQuery();
		    
		    int index = 0;
		    while(rs.next()) {		    	
		    	aSessionId[index] = rs.getLong("sessionid");		    	
		    	index++;
		    }
		    
		    conn.commit();
		    conn.setAutoCommit(true);
		    
		    
		    int iFoldSessionCount = iSessioncount/numOfFolds;
		    int iFractionalSession = iSessioncount%numOfFolds;
		    
		    
		    
		    
		    int iIndexPointer = 0;
		    for(int i=0;i<numOfFolds;i++) {
		    	Fold oFold = new Fold();
		    	oFold.startIndex = iIndexPointer;
		    	iIndexPointer+= (iFoldSessionCount - 1) ;
		    		    
		    	if(iFractionalSession !=0) {
		    		iFractionalSession--;
		    		iIndexPointer++;
		    	}
		    	
		    	oFold.endIndex = iIndexPointer;
		    	
		    	aFold[i] = oFold;
		    	iIndexPointer++;	    	
		    }
		    
		    
		    int iTestFold_Pointer = numOfFolds-1;
		    
		    String path = Configuration.getTestInputDir();
		    File oFile = new File(path);
		    try {
				delete(oFile);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		    
		    oFile.mkdir();
		    File oFileTraining;
		    File oFileTest;
		    
		    int k=0;
		    while(iTestFold_Pointer >=0) {
		    	
		    	String foldpath = path + "/fold"+ (k+1);
	    		
	    		oFileTraining = new File(foldpath);
	    		oFileTraining.mkdir();
	    		
	    		String trainingfilePath = foldpath + "/training.dat";
	    		String testfilePath = foldpath + "/test.dat";
	    		
	    		
	    		oFileTraining = new File(trainingfilePath);
    			oFileTest = new File(testfilePath);
    			 
    			try {
    				oFileTraining.createNewFile();
    				oFileTest.createNewFile();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
	    		
    			FileWriter fstreamTraining = null;
    			FileWriter fstreamTest = null;
    			
    			BufferedWriter outTraining = null;
    			BufferedWriter outTest = null;
    			
				try {
					fstreamTraining = new FileWriter(trainingfilePath);
					fstreamTest = new FileWriter(testfilePath);
					
					outTraining = new BufferedWriter(fstreamTraining);
					outTest = new BufferedWriter(fstreamTest);
					
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		    	
				try{
					for(int i=0;i<numOfFolds;i++) {
						
						if(i!=iTestFold_Pointer)  {
		    			//Training Fold
							//System.out.println("Training Fold" + aFold[i].startIndex + ":" + aFold[i].endIndex);		    	   			  
			    			for(int j= aFold[i].startIndex;j<=aFold[i].endIndex;j++) {
			    				
			    				String sql = "select * from sessionfragment where sessionid = ?";
			    				stmt = conn.prepareStatement(sql);
			    				stmt.setLong(1, aSessionId[j]);
			    			    rs = stmt.executeQuery();
			    				
			    				while(rs.next()) {
			    					
			    						outTraining.write(rs.getLong("sessionid") + ","+rs.getLong("fragmentid") + "," + rs.getDouble("importance"));
			    						outTraining.newLine();
			    						outTraining.flush();								
			    				}
			    			}
		    			
		    	
						}
						else {
							//System.out.println("Test Fold" + aFold[i].startIndex + ":" + aFold[i].endIndex);
							//Test Fold
							int j;
							for(j= aFold[i].startIndex;j<aFold[i].endIndex;j++) {
							
								outTest.write(aSessionId[j]+ ",");
								outTest.flush();
							}
							outTest.write(aSessionId[j] + "");
							outTest.flush();
						}
					}
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				try {
					outTraining.close();
					outTest.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
    			
		    	iTestFold_Pointer--;
		    	k++;
		    }
		     
		    
			//conn.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		System.out.println("Model Input Generation Ends");
	}
	
	static void delete(File f) throws IOException {
		  if (f.isDirectory()) {
		    for (File c : f.listFiles())
		      delete(c);
		  }
		  if (f.exists() && !f.delete())
		    throw new FileNotFoundException("Failed to delete file: " + f);
		}
}
